package com.laoxiang.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.laoxiang.execption.LxAdminException;
import com.laoxiang.modules.system.entity.SysDept;
import com.laoxiang.modules.system.entity.SysMenu;
import com.laoxiang.modules.system.entity.SysUser;
import com.laoxiang.modules.system.entity.vo.DeptTreeVO;
import com.laoxiang.modules.system.entity.vo.MenuTreeVo;
import com.laoxiang.modules.system.mapper.SysDeptMapper;
import com.laoxiang.modules.system.mapper.SysUserMapper;
import com.laoxiang.modules.system.service.SysDeptService;
import com.laoxiang.utils.AppHttpCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 部门信息表(SysDept)表服务实现类
 *
 * @author db
 * @since 2023-09-03 22:33:50
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Override
    public List<SysDept> getDeptList(SysDept sysDept) {
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(sysDept.getName()),SysDept::getName,sysDept.getName());
        queryWrapper.eq(Objects.nonNull(sysDept.getStatus()),SysDept::getStatus,sysDept.getStatus());
        //排序 parent_id和order_num
        queryWrapper.orderByAsc(SysDept::getParentId,SysDept::getDeptSort);
        List<SysDept> sysDeptList = sysDeptMapper.selectList(queryWrapper);
//        List<SysDept> deptList = buildDeptTree(sysDeptList);
        return sysDeptList;
    }


    private List<SysDept> buildDeptTree(List<SysDept> sysDepts) {
        List<SysDept> deptList= sysDepts.stream()
                .filter(o -> o.getParentId().equals(0L))
                .map(o -> o.setChildren(getChildren(sysDepts, o)))
                .collect(Collectors.toList());
        return deptList;
    }

    private List<SysDept> getChildren(List<SysDept> sysDeptList,SysDept option){
        List<SysDept> deptTreeList = sysDeptList.stream()
                .filter(o -> Objects.equals(o.getParentId(), option.getId()))
                .map(o -> o.setChildren(getChildren(sysDeptList, o)))
                .collect(Collectors.toList());

        return deptTreeList;
    }


    @Override
    public List<DeptTreeVO> getDeptTreeSelect() {
        List<SysDept> deptList = sysDeptMapper.selectList(null);
        List<DeptTreeVO> deptTreeVOList = buildDeptSelectTree(deptList);
        return deptTreeVOList;
    }

    @Override
    public int addDept(SysDept sysDept) {
        // 查询父节点的状态是否正常
        SysDept sysDeptInfo = sysDeptMapper.selectById(sysDept.getParentId());
        if(sysDeptInfo.getStatus() == 0){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_ERROR);
        }

        // 检查部门名称是否存在
        boolean flag = checkDeptNameUnique(sysDept);
        if(!flag){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_EXIST);
        }
        int insert = sysDeptMapper.insert(sysDept);
        return insert;
    }

    @Override
    public SysDept getSysDeptById(Long deptId) {
        SysDept sysDept = sysDeptMapper.selectById(deptId);
        return sysDept;
    }

    @Override
    public boolean checkDeptNameUnique(SysDept sysDept) {
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDept::getName,sysDept.getName());
        queryWrapper.eq(SysDept::getParentId,sysDept.getParentId());
        List<SysDept> deptList = sysDeptMapper.selectList(queryWrapper);
        if(!CollectionUtils.isEmpty(deptList) && deptList.get(0).getId().longValue() != sysDept.getId().longValue()){
            return false;
        }

        return true;
    }

    @Override
    public void updateDept(SysDept sysDept) {

        boolean flag = checkDeptNameUnique(sysDept);
        if(!flag){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_EXIST);
        }
        if(sysDept.getParentId() == sysDept.getId()){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_PARENT_ERROR);
        }
        sysDeptMapper.updateById(sysDept);

    }

    @Override
    public void deleteDeptById(Long deptId) {

        // 是否存在部门子节点
        if(hasChildByDeptId(deptId)){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_HAS_CHILDREN);
        }
        // 查询部门是否存在用户
        if(checkDeptExistUser(deptId)){
            throw new LxAdminException(AppHttpCodeEnum.DEPT_EXIST_USER);
        }

        sysDeptMapper.deleteById(deptId);
    }

    @Override
    public boolean checkDeptExistUser(Long deptId) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getDeptId,deptId);
        Integer count = sysUserMapper.selectCount(queryWrapper);
        return count>0;
    }

    @Override
    public boolean hasChildByDeptId(Long deptId) {
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDept::getParentId,deptId);
        Integer count = sysDeptMapper.selectCount(queryWrapper);
        return count>0;
    }

    private List<DeptTreeVO> buildDeptSelectTree(List<SysDept> depts) {
        List<DeptTreeVO> deptTreeVos = depts.stream()
                .map(m -> new DeptTreeVO(m.getId(), m.getName(), m.getParentId(), null))
                .collect(Collectors.toList());
        List<DeptTreeVO> deptTreeVoList = deptTreeVos.stream()
                .filter(o -> o.getParentId().equals(0L))
                .map(o -> o.setChildren(getChildList(deptTreeVos, o)))
                .collect(Collectors.toList());
        return deptTreeVoList;
    }

    private List<DeptTreeVO> getChildList(List<DeptTreeVO> list, DeptTreeVO option) {
        List<DeptTreeVO> deptTreeVoList = list.stream()
                .filter(o -> Objects.equals(o.getParentId(), option.getId()))
                .map(o -> o.setChildren(getChildList(list, o)))
                .collect(Collectors.toList());
        return deptTreeVoList;
    }
}

